# Based on the work by straga (https://github.com/straga)
# https://github.com/straga/micropython_lcd/blob/master/device/JC3248W535/driver/axs15231b/_axs15231b_init_type1.py
# Copyright (c) 2024 - 2025 Kevin G. Schlosser

import time
from micropython import const  # NOQA
import lvgl as lv  # NOQA


_AXS_LCD_NOP = const(0x00)  # No operation (C)
_AXS_LCD_SWRESET = const(0x01)  # Software reset (C)
_AXS_LCD_RDDID = const(0x04)  # Read display (R)
_AXS_LCD_RDNUMED = const(0x05)  # Read Number of the Errors on DSI (R)
_AXS_LCD_RDDST = const(0x09)  # Read display status (R)
_AXS_LCD_RDDPM = const(0x0A)  # Read display power (R)
_AXS_LCD_RDDMADC = const(0x0B)  # Read memory data access control (R)
_AXS_LCD_RDDIPF = const(0x0C)  # Read Interface Pixel Format (R)
_AXS_LCD_RDDIM = const(0x0D)  # Read display image (R)
_AXS_LCD_RDDSM = const(0x0E)  # Read display signal (R)
_AXS_LCD_RDDSDR = const(0x0F)  # Read display self-diagnostic result (R)
_AXS_LCD_SLPIN = const(0x10)  # Sleep in (C)
_AXS_LCD_SLPOUT = const(0x11)  # Sleep out (C)
_AXS_LCD_PTLON = const(0x12)  # Partial mode on (C)
_AXS_LCD_NORON = const(0x13)  # Partial mode off(Normal) (C)
_AXS_LCD_INVOFF = const(0x20)  # Display inversion off (C)
_AXS_LCD_INVON = const(0x21)  # Display inversion on (C)
_AXS_LCD_ALLPOFF = const(0x22)  # All pixel off (C)
_AXS_LCD_ALLPON = const(0x23)  # All pixel on (C)
_AXS_LCD_ALLPFILL = const(0x24)  # All pixel fill given color (W)
_AXS_LCD_GAMSET = const(0x26)  # Gamma curve set (W)
_AXS_LCD_DISPOFF = const(0x28)  # Display off (C)
_AXS_LCD_DISPON = const(0x29)  # Display on (C)
_AXS_LCD_CASET = const(0x2A)  # Column address set (W)
_AXS_LCD_RASET = const(0x2B)  # Row address set (W)
_AXS_LCD_RAMWR = const(0x2C)  # Memory write any length MIPI/SPI/QSPI/DBI (W)
_AXS_LCD_RAMRD = const(0x2E)  # Memory read any length SPI/QSPI/DBI (R)
_AXS_LCD_RAWFILL = const(0x2F)  # Memory fill given color at window (W)
_AXS_LCD_PTLAR = const(0x30)  # Partial start/end address set (W)
_AXS_LCD_PTLARC = const(0x31)  # set_partial_columns (W)
_AXS_LCD_VSCRDEF = const(0x33)  # Vertical scrolling definition (W)
_AXS_LCD_TEOFF = const(0x34)  # Tearing effect line off (C)
_AXS_LCD_TEON = const(0x35)  # Tearing effect line on (W)
_AXS_LCD_MADCTL = const(0x36)  # Memory data access control (W)
_AXS_LCD_VSCRSADD = const(0x37)  # Vertical scrolling start address (W)
_AXS_LCD_IDMOFF = const(0x38)  # Idle mode off (C)
_AXS_LCD_IDMON = const(0x39)  # Idle mode on (C)
_AXS_LCD_IPF = const(0x3A)  # Interface pixel format (W)
_AXS_LCD_RAMWRC = const(0x3C)  # Memory write continue any length MIPI/SPI/QSPI/DBI (W)
_AXS_LCD_RAMRDC = const(0x3E)  # Memory read continue any length SPI/QSPI/DBI (R)
_AXS_LCD_TESCAN = const(0x44)  # Set tear scanline (W)
_AXS_LCD_RDTESCAN = const(0x45)  # Get tear scanline (R)
_AXS_LCD_WRDISBV = const(0x51)  # Write display brightness value (W)
_AXS_LCD_RDDISBV = const(0x52)  # Read display brightness value (R)
_AXS_LCD_WRCTRLD = const(0x53)  # Write CTRL display (W)
_AXS_LCD_RDCTRLD = const(0x54)  # Read CTRL dsiplay (R)
_AXS_LCD_RDFCHKSU = const(0xAA)  # Read First Checksum (R)
_AXS_LCD_RDCCHKSU = const(0xAA)  # Read Continue Checksum (R)
_AXS_LCD_RDID1 = const(0xDA)  # Read ID1 (R)
_AXS_LCD_RDID2 = const(0xDB)  # Read ID2 (R)
_AXS_LCD_RDID3 = const(0xDC)  # Read ID3 (R)
_AXS_LCD_DSTB = const(0x90)  # Enter Deep-Standby (W)


def init(self):
    param_buf = self._param_buf
    param_mv = self._param_mv

    self.set_params(_AXS_LCD_SLPOUT)
    time.sleep_ms(100)  # NOQA

    # Pixel size
    color_size = lv.color_format_get_size(self._color_space)
    if color_size == 2:
        pixel_format = 0x55
    else:
        pixel_format = 0x66

    param_buf[0] = pixel_format
    self.set_params(_AXS_LCD_IPF, param_mv[:1])

    self.set_params(_AXS_LCD_TEOFF)

    # 0xD0 BRIGHTNESS
    param_buf[0] = 0xD0
    self.set_params(_AXS_LCD_WRDISBV, param_mv[:1])

    param_buf[:8] = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5])
    self.set_params(0xBB, param_mv[:8])

    param_buf[:17] = bytearray([0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x64, 0x3F, 0x20, 0x05, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00])
    self.set_params(0xA0, param_mv[:17])

    param_buf[:31] = bytearray([0x30, 0x04, 0x0A, 0x3C, 0xEC, 0x54, 0xC4, 0x30, 0xAC, 0x28, 0x7F, 0x7F, 0x7F, 0x20, 0xF8, 0x10, 0x02, 0xFF, 0xFF, 0xF0, 0x90, 0x01, 0x32, 0xA0, 0x91, 0xC0, 0x20, 0x7F, 0xFF, 0x00, 0x54])
    self.set_params(0xA2, param_mv[:31])

    param_buf[:30] = bytearray([0x30, 0xAC, 0x21, 0x24, 0x08, 0x09, 0x10, 0x01, 0xAA, 0x14, 0xC2, 0x00, 0x22, 0x22, 0xAA, 0x03, 0x10, 0x12, 0x40, 0x14, 0x1E, 0x51, 0x15, 0x00, 0x40, 0x10, 0x00, 0x03, 0x3D, 0x12])
    self.set_params(0xD0, param_mv[:30])

    param_buf[:22] = bytearray([0xA0, 0x06, 0xAA, 0x08, 0x08, 0x02, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x55, 0x55])
    self.set_params(0xA3, param_mv[:22])

    param_buf[:30] = bytearray([0x33, 0x04, 0x02, 0x02, 0x71, 0x05, 0x24, 0x55, 0x02, 0x00, 0x41, 0x00, 0x53, 0xFF, 0xFF, 0xFF, 0x4F, 0x52, 0x00, 0x4F, 0x52, 0x00, 0x45, 0x3B, 0x0B, 0x02, 0x0D, 0x00, 0xFF, 0x40])
    self.set_params(0xC1, param_mv[:30])

    param_buf[:11] = bytearray([0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01])
    self.set_params(0xC3, param_mv[:11])

    param_buf[:29] = bytearray([0x00, 0x24, 0x33, 0x90, 0x50, 0xea, 0x64, 0x32, 0xC8, 0x64, 0xC8, 0x32, 0x90, 0x90, 0x11, 0x06, 0xDC, 0xFA, 0x04, 0x03, 0x80, 0xFE, 0x10, 0x10, 0x00, 0x0A, 0x0A, 0x44, 0x50])
    self.set_params(0xC4, param_mv[:29])

    param_buf[:23] = bytearray([0x18, 0x00, 0x00, 0x03, 0xFE, 0x78, 0x33, 0x20, 0x30, 0x10, 0x88, 0xDE, 0x0D, 0x08, 0x0F, 0x0F, 0x01, 0x78, 0x33, 0x20, 0x10, 0x10, 0x80])
    self.set_params(0xC5, param_mv[:23])

    param_buf[:20] = bytearray([0x05, 0x0A, 0x05, 0x0A, 0x00, 0xE0, 0x2E, 0x0B, 0x12, 0x22, 0x12, 0x22, 0x01, 0x00, 0x00, 0x3F, 0x6A, 0x18, 0xC8, 0x22])
    self.set_params(0xC6, param_mv[:20])

    param_buf[:20] = bytearray([0x50, 0x32, 0x28, 0x00, 0xa2, 0x80, 0x8f, 0x00, 0x80, 0xff, 0x07, 0x11, 0x9F, 0x6f, 0xff, 0x26, 0x0c, 0x0d, 0x0e, 0x0f])
    self.set_params(0xC7, param_mv[:20])

    param_buf[:4] = bytearray([0x33, 0x44, 0x44, 0x01])
    self.set_params(0xC9, param_mv[:4])

    param_buf[:27] = bytearray([0x34, 0x1E, 0x88, 0x58, 0x13, 0x18, 0x56, 0x18, 0x1E, 0x68, 0xF7, 0x00, 0x65, 0x0C, 0x22, 0xC4, 0x0C, 0x77, 0x22, 0x44, 0xAA, 0x55, 0x04, 0x04, 0x12, 0xA0, 0x08])
    self.set_params(0xCF, param_mv[:27])

    param_buf[:30] = bytearray([0x3E, 0x3E, 0x88, 0x00, 0x44, 0x04, 0x78, 0x33, 0x20, 0x78, 0x33, 0x20, 0x04, 0x28, 0xD3, 0x47, 0x03, 0x03, 0x03, 0x03, 0x86, 0x00, 0x00, 0x00, 0x30, 0x52, 0x3f, 0x40, 0x40, 0x96])
    self.set_params(0xD5, param_mv[:30])

    param_buf[:30] = bytearray([0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, 0x95, 0x00, 0x01, 0x83, 0x75, 0x36, 0x20, 0x75, 0x36, 0x20, 0x3F, 0x03, 0x03, 0x03, 0x10, 0x10, 0x00, 0x04, 0x51, 0x20, 0x01, 0x00])
    self.set_params(0xD6, param_mv[:30])

    param_buf[:19] = bytearray([0x0a, 0x08, 0x0e, 0x0c, 0x1E, 0x18, 0x19, 0x1F, 0x00, 0x1F, 0x1A, 0x1F, 0x3E, 0x3E, 0x04, 0x00, 0x1F, 0x1F, 0x1F])
    self.set_params(0xD7, param_mv[:19])

    param_buf[:12] = bytearray([0x0B, 0x09, 0x0F, 0x0D, 0x1E, 0x18, 0x19, 0x1F, 0x01, 0x1F, 0x1A, 0x1F])
    self.set_params(0xD8, param_mv[:12])

    param_buf[:13] = bytearray([0x00, 0x0D, 0x0F, 0x09, 0x0B, 0x1F, 0x18, 0x19, 0x1F, 0x01, 0x1E, 0x1A, 0x1F])
    self.set_params(0xD9, param_mv[:13])

    param_buf[:12] = bytearray([0x0C, 0x0E, 0x08, 0x0A, 0x1F, 0x18, 0x19, 0x1F, 0x00, 0x1E, 0x1A, 0x1F])
    self.set_params(0xDD, param_mv[:12])

    param_buf[:8] = bytearray([0x44, 0x73, 0x4B, 0x69, 0x00, 0x0A, 0x02, 0x90])
    self.set_params(0xDF, param_mv[:8])

    param_buf[:17] = bytearray([0x19, 0x20, 0x0A, 0x13, 0x0E, 0x09, 0x12, 0x28, 0xD4, 0x24, 0x0C, 0x35, 0x13, 0x31, 0x36, 0x2f, 0x03])
    self.set_params(0xE0, param_mv[:17])

    param_buf[:17] = bytearray([0x38, 0x20, 0x09, 0x12, 0x0E, 0x08, 0x12, 0x28, 0xC5, 0x24, 0x0C, 0x34, 0x12, 0x31, 0x36, 0x2f, 0x27])
    self.set_params(0xE1, param_mv[:17])

    param_buf[:17] = bytearray([0x19, 0x20, 0x0A, 0x11, 0x09, 0x06, 0x11, 0x25, 0xD4, 0x22, 0x0B, 0x33, 0x12, 0x2D, 0x32, 0x2f, 0x03])
    self.set_params(0xE2, param_mv[:17])

    param_buf[:17] = bytearray([0x38, 0x20, 0x0A, 0x11, 0x09, 0x06, 0x11, 0x25, 0xC4, 0x21, 0x0A, 0x32, 0x11, 0x2C, 0x32, 0x2f, 0x27])
    self.set_params(0xE3, param_mv[:17])

    param_buf[:17] = bytearray([0x19, 0x20, 0x0D, 0x14, 0x0D, 0x08, 0x12, 0x2A, 0xD4, 0x26, 0x0E, 0x35, 0x13, 0x34, 0x39, 0x2f, 0x03])
    self.set_params(0xE4, param_mv[:17])

    param_buf[:17] = bytearray([0x38, 0x20, 0x0D, 0x13, 0x0D, 0x07, 0x12, 0x29, 0xC4, 0x25, 0x0D, 0x35, 0x12, 0x33, 0x39, 0x2f, 0x27])
    self.set_params(0xE5, param_mv[:17])

    param_buf[:8] = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
    self.set_params(0xBB, param_mv[:8])

    self.set_params(_AXS_LCD_NORON)
    self.set_params(_AXS_LCD_SLPOUT)
    time.sleep_ms(200)  # NOQA

    self.set_params(_AXS_LCD_DISPON)
    time.sleep_ms(200)  # NOQA

    param_buf[:4] = bytearray([0x00, 0x00, 0x00, 0x00])
    self.set_params(_AXS_LCD_RAMWR, param_mv[:4])

    self.set_params(_AXS_LCD_ALLPOFF)
    time.sleep_ms(200)  # NOQA
